package com.zzp.sms.security.filter;

import com.zzp.sms.security.constant.Constants;
import com.zzp.sms.security.domain.SmsCode;
import com.zzp.sms.security.handler.CustomizeAuthenticationFailureHandler;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 佐斯特勒
 * <p>
 * 短信验证过滤器
 * </p>
 * @version v1.0.0
 * @date 2020/1/12 23:41
 * @see SmsCodeFilter
 **/
@Component
public class SmsCodeFilter extends OncePerRequestFilter {

    private final static Logger log = LoggerFactory.getLogger(SmsCodeFilter.class);

    /**
     * 自定义认证失败操作
     */
    @Resource
    private CustomizeAuthenticationFailureHandler authenticationFailureHandler;


    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp,
                                    FilterChain filterChain) throws ServletException, IOException {
        // 获取请求的uri
        var uri = req.getRequestURI();
        // 判断是否是post请求的电话登录地址
        if ("POST".equalsIgnoreCase(req.getMethod()) && Constants.SMS_LOGIN_URI.equals(uri)) {
            try {
                validateProcess(req, resp);
            } catch (AuthenticationException ex) {
                authenticationFailureHandler.onAuthenticationFailure(req, resp, ex);
                return;
            }
        }
        filterChain.doFilter(req,resp);
    }

    /**
     * 信息验证
     *
     * @param req  http请求
     * @param resp http响应
     * @throws IOException      io异常
     * @throws ServletException servlet异常
     */
    private void validateProcess(HttpServletRequest req, HttpServletResponse resp)
            throws IOException, ServletException {
        var smsCode = (SmsCode) req.getSession().getAttribute(Constants.SMS_CODE_SESSION_KEY);
        // 获取接收参数
        var code = req.getParameter("msgCode");
        log.info("code:"+code);
        if (Strings.isBlank(code)) {
            throw new InternalAuthenticationServiceException("短信验证码不能为空.");
        }
        if (null == smsCode) {
            throw new InternalAuthenticationServiceException("短信验证码不存在.");
        }

        if (smsCode.isExpire()) {
            throw new InternalAuthenticationServiceException("短信验证码已失效.");
        }
        if (!code.equals(smsCode.getCode())) {
            throw new InternalAuthenticationServiceException("短信验证码错误.");
        }
    }
}
